// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license


#include "stdafx.h"
#include "WorldBuilder.h"
#include "World.h"
#include "View3d.h"

World::World()
: m_nodeManager(this)
{
}
 
World::~World()
{
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


NodeManager& World::getNodeManager()
{
    return m_nodeManager;
}

LightManager& World::getLightManager()
{
    return m_lightManager;
}

MaterialManager& World::getMaterialManager()
{
    return m_materialManager;
}

ShaderManager& World::getShaderManager()
{
    return m_shaderManager;
}

TextureManager& World::getTextureManager()
{
    return m_textureManager;
}

MeshManager& World::getMeshManager()
{
    return m_meshManager;
}


// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


void World::clear()
{
    m_lightManager.clear();
    m_materialManager.clear();
    m_nodeManager.clear();
    m_textureManager.clear();
    m_shaderManager.clear();
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Serialization

void World::write(std::wostream& os) const
{
    // We write materials before nodes because at the time the nodes are 
    // loaded, the materials must be available (so that we can check
    // if the loaded material names correspond to actual materials that
    // have been previously loaded)

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    // Write materials

    os << m_materialManager.getMaterialCount() << "\n\n";

    typedef MaterialManager::MaterialIt MaterialIt;
    for(MaterialIt it = m_materialManager.beginMaterials(); 
        it != m_materialManager.endMaterials(); ++it)
    {
        ref<Material> mat = *it;
        mat->write(os);
        os << "\n";
    }
    os << "\n";

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    // Write nodes

    os << m_nodeManager.getNodes().size() << "\n\n";

    for(ConstNodeIterator it = m_nodeManager.nodesBegin(); 
        it != m_nodeManager.nodesEnd(); ++it)
    {
        ref<Node> node = *it;
        m_nodeManager.writeNode(os, node);
        os << "\n";
    }
}

void World::read(std::wistream& is)
{
    // We must start from scratch
    clear();

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    // Read materials

    size_t materialCount;
    is >> materialCount;

    for(size_t i = 0; i < materialCount; ++i)
    {
        ref<Material> mat(new Material);
        mat->read(is);
        m_materialManager.registerMaterial(mat);
    }

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    // Read nodes

    size_t nodeCount;
    is >> nodeCount;
    
    for(size_t i = 0; i < nodeCount; ++i)
    {
        m_nodeManager.readNode(is);
    }
}

